﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Fiuba.Algo3.Titiritero;
using AlgoHero.Modelo;
using System.Drawing;
using AlgoHero.Controlador;

namespace AlgoHero.Vista
{
    public class PreparadorVistaNivel
    {

        private IList<IObjetoVivo> objetosVivos;
        private IList<IDibujable> dibujables;
        private Cancion cancion;
        private IList<Color> coloresBotones;
        private int anchoInstrumento;
        private int altoInstrumento;
        private int posicionXInstrumento;
        private int posicionYInstrumento;
        private Color colorInstrumento;
        private TimeSpan tiempoDePreparacion;
        private VistaPuntaje vistaPuntaje;
        private VistaPuntaje vistaTeclasPerdidas;

        public PreparadorVistaNivel()
        {
            this.objetosVivos = new List<IObjetoVivo>();
            this.dibujables = new List<IDibujable>();
            this.coloresBotones = new List<Color>();
            this.coloresBotones.Add(Color.Red);
            this.coloresBotones.Add(Color.Blue);
            this.coloresBotones.Add(Color.Green);
            this.coloresBotones.Add(Color.Yellow);
            this.coloresBotones.Add(Color.Black);
            this.coloresBotones.Add(Color.Orange);
            this.coloresBotones.Add(Color.Navy);
            this.anchoInstrumento = 300;//pix
            this.altoInstrumento = 700;// 700 alto superficie de dibujo
            this.posicionXInstrumento = (800 - this.anchoInstrumento) / 2;// 800 ancho superficie de dibujo
            this.posicionYInstrumento = 0;
            this.colorInstrumento = Color.Chocolate;
            this.vistaPuntaje = new VistaPuntaje(30, 80, "Puntaje: ", 18, Color.White);
            this.vistaTeclasPerdidas = new VistaPuntaje(30, 120, "Teclas Perdidas: ", 18, Color.White);

        }

        public IList<IDibujable> DameLosDibujables()
        {
            return this.dibujables;
        }

        public IList<IObjetoVivo> DameLosObjetosVivos()
        {
            return this.objetosVivos;
        }

        public TimeSpan DameElTiempoParaQueElUsuarioSePrepare()
        {
            return tiempoDePreparacion;
        }

        public void PreparaLaVistaDelNivel(Nivel nivel, Cancion cancion, double intervaloDeSimulacion)
        {
            this.cancion = cancion;
            VistaInstrumento vistaInstrumento = new VistaInstrumento(this.anchoInstrumento, this.altoInstrumento, this.posicionXInstrumento, this.posicionYInstrumento, this.cancion.CantidadDeTeclas(), this.colorInstrumento, intervaloDeSimulacion);
            this.dibujables.Add(vistaInstrumento);

            IDictionary<Tecla, int> mapeoTeclaANumeroDeCarril = this.MapearTeclaANumeroDeCarril();                                       

            double tiempoInicioAcorde = 0;
            IList<Tecla> teclasDeAcorde;
            int posicionXEnCarril;
            int posicionYEnCarril;
            int radioBoton = vistaInstrumento.AnchoPermitido;
            int numeroDeCarril;
            int incrementoY = vistaInstrumento.IncrementoY;
            this.tiempoDePreparacion = vistaInstrumento.TiempoQueElPrimerBotonTocaLaRegionHabilitada();
            VistaBoton boton;
            
            this.dibujables.Add(this.vistaPuntaje);
            this.dibujables.Add(this.vistaTeclasPerdidas);


            while (tiempoInicioAcorde != -1)
            {

                teclasDeAcorde = this.cancion.ObtenerTeclasAPresionar(tiempoInicioAcorde);

                posicionYEnCarril = (int)vistaInstrumento.ObtenerPosicionYEnCarril(tiempoInicioAcorde);

                foreach (Tecla tecla in teclasDeAcorde)
                {
                    numeroDeCarril = mapeoTeclaANumeroDeCarril[tecla];

                    posicionXEnCarril = vistaInstrumento.ObtenerPosicionXEnCarril(numeroDeCarril);

                    boton = new VistaBoton(radioBoton,posicionXEnCarril,posicionYEnCarril, incrementoY,coloresBotones.ElementAt(numeroDeCarril-1), tecla);
                    dibujables.Add(boton);
                    objetosVivos.Add(boton);
                }

                tiempoInicioAcorde = this.cancion.ObtenerTiempoDeProxAcorde(tiempoInicioAcorde);
            }

        }

        public void Resetear()
        {
            this.dibujables.Clear();
            this.objetosVivos.Clear();
        }

        public IObservadorDePuntaje DameElObservadorDePuntaje()
        {
            return this.vistaPuntaje;
        }

        public IObservadorDePuntaje DameElObservadorDeTeclasPerdidas()
        {
            return this.vistaTeclasPerdidas;
        }

        private IDictionary<Tecla, int> MapearTeclaANumeroDeCarril()
        {
            IEqualityComparer<Tecla> comparadorTeclas = Tecla.GetEqualityComparer();
            Dictionary<Tecla, int> mapeoTeclaANumeroDeCarril = new Dictionary<Tecla, int>(comparadorTeclas);
            IList<Tecla> teclasHabilitadas = this.cancion.TeclasHabilitadas();
            int numeroDeCarril = 1;

            foreach (Tecla tecla in teclasHabilitadas)
            {

                mapeoTeclaANumeroDeCarril.Add(tecla, numeroDeCarril);
                numeroDeCarril++;
            }

            return mapeoTeclaANumeroDeCarril;
        }
    }
}
